#include "solve.h"

unsigned char Snext(grille g, unsigned char i)
{
  i = (i+1) % 81;
  while( GgetFixedIndex(g, i) == 1 )
    i = (i+1) % 81;
  return i;
}

unsigned char Sprev(grille g, unsigned char i)
{
  if( i == 0 ) i = 80;
  else i--;

  while( GgetFixedIndex(g, i) == 1 )
  {
    if( i == 0 ) i = 80;
    else i--;
  }
  return i;
}

unsigned char Sincr(grille g, unsigned char i)
{
  unsigned char n = GgetNumberIndex(g, i) + 1;
  if( n > 9 )
  {
    GsetNumberIndex(g, i, 0);
    return 0;
  }
  else
  {
    GsetNumberIndex(g, i, n);
    return 1;
  }
}

void SsolveGrid(grille g)
{
  if( GisOver(g) == 0 )
  {
    // On mets toutes les caes non fixées à 0
    GresetNotFixedBoxes(g);
  
    // Si la première case est fixée, on solve à partir
    // de la première case non fixée
    if( GgetFixedIndex(g, 0) == 1 )
      SsolveIter(g, Snext(g, 0));
    else // On solve à partir de la première case
      SsolveIter(g, 0);

    ClrScr();
    GdisplayAllNumbers(g);
  }
}

// Fonction récursive
// On l'appelle au début quand on est sur la première case non fixée qui
// est remplie par un 0
void SsolveRec(grille g, unsigned char i)
{
  if( GisOver(g) == 0 )
  {
    // Si la grille n'est pas terminée, on solve

    // Petit display
    //ClrScr();
    //GdisplayAllNumbers(g);
    //ngetchx();

    if( Sincr(g, i) == 0 )
    {
      // On a dépassé 9, on go back et on solve
      SsolveRec(g, Sprev(g, i));
    }
    else
    {
      if( CBoxAllIndex(g, i) == 1 )
      {
        // Si le nombre est valide, on avance et on solve
        SsolveRec(g, Snext(g, i));
      }
      else
      {
        // Sinon, on solve sans avancer
        SsolveRec(g, i);
      }
    }
  }
  // Sinon, on a fini !
}

void SsolveIter(grille g, unsigned char i)
{
  unsigned char current = i, over = 1;
  while( GisOver(g) == 0 || over == 0)
  {
    over = 1;
    // On essaie d'incrémenter
    if( Sincr(g, current) == 1 )
    {
      // On a réussi a incrémenter (<= 9)
      // On vérifie la validité
      if( CBoxAllIndex(g, current) == 1 )
      {
        // Le nombre est valide
        // On passe à la case suivante
        current = Snext(g, current);
      }
      else
      {
        // Le nombre n'est pas valide
        // On ne bouge pas mais on met over à 0
        // car on ne peut pas avoir terminé
        // et il faut reboucler
        over = 0;
      }
    }
    else
    {
      // On n'a pas réussi a incrémenter,
      // La case a été mise a 0
      // On reviens en arrière
      current = Sprev(g, current);
    }
  }
}

